;;; +ivy.el --- config for completion using ivy -*- lexical-binding: t -*-

;;; Commentary:

;;; Code:

;; Incremental Vertical completYon
(use-package ivy
  :defer t
  :diminish ivy-mode
  :hook
  ((after-init) . ivy-mode)
  ((ivy-mode) . counsel-mode)
  :config
  (setq ivy-use-virtual-buffers t ;; recentf
	    ivy-count-format "(%d/%d) "
	    enable-recursive-minibuffers t
	    ivy-display-style 'fancy
	    ivy-ignore-buffers '("^\\*autoconnect-NOX"
			                 "^\\*NOX "
			                 "^\\*flycheck-posframe-buffer")
	    ivy-height 10)
  :bind
  (("C-x b" . 'ivy-switch-buffer)))

;; Using posframe to show Ivy
(use-package ivy-posframe
  :defer t
  :diminish ivy-posframe-mode
  :if (display-graphic-p)
  :custom
  (ivy-display-function #'ivy-posframe-display-at-frame-center)
  ;; (ivy-posframe-width 130)
  ;; (ivy-posframe-height 11)
  (ivy-posframe-height-alist '((counsel-describe-function    . 20)
                               (counsel-describe-variable    . 20)
                               (counsel-descbinds            . 20)
                               (counsel-find-file            . 20)
                               (counsel-M-x                  . 20)
                               (counsel-yank-pop             . 20)
                               (embark-bindings              . 20)
                               (ivy-switch-buffer            . 20)
                               (ivy-yasnippet                . 20)))
  (ivy-posframe-parameters
   '((left-fringe  . 5)
     (right-fringe . 5)))
  :hook
  ((after-init) . ivy-posframe-mode))

;; More friendly display transformer for ivy
(use-package ivy-rich
  :defer t
  :init
  (ivy-rich-mode 1))

;; Better experience with icons for ivy.
(use-package all-the-icons-ivy-rich
  :init
  (all-the-icons-ivy-rich-mode 1))

;; Preview yasnippets with Ivy
(use-package ivy-yasnippet
  :defer t
  :after yasnippet
  :bind
  (("C-c y" . 'ivy-yasnippet)))

;; Better sorting and filtering candidates.
(use-package prescient
  :defer t
  :commands prescient-persist-mode
  :init
  (setq prescient-filter-method '(literal regexp initialism fuzzy))
  (prescient-persist-mode 1))

(use-package ivy-prescient
  :defer t
  :commands ivy-prescient-re-builder
  :init
  (defun ivy-prescient-non-fuzzy (str)
    "Generate an Ivy-formatted non-fuzzy regexp list for the given STR.
This is for use in `ivy-re-builders-alist'."
    (let ((prescient-filter-method '(literal regexp)))
      (ivy-prescient-re-builder str)))
  (setq ivy-prescient-retain-classic-highlighting t
	    ivy-re-builders-alist
	    '((counsel-ag . ivy-prescient-non-fuzzy)
	      (counsel-rg . ivy-prescient-non-fuzzy)
	      (counsel-pt . ivy-prescient-non-fuzzy)
	      (counsel-grep . ivy-prescient-non-fuzzy)
	      (counsel-imenu . ivy-prescient-non-fuzzy)
	      (counsel-yank-pop . ivy-prescient-non-fuzzy)
	      (lsp-ivy-workspace-symbol . ivy-prescient-non-fuzzy)
	      (lsp-ivy-global-workspace-symbol . ivy-prescient-non-fuzzy)
	      (insert-char . ivy-prescient-non-fuzzy)
	      (counsel-unicode-char . ivy-prescient-non-fuzzy)
	      (t . ivy-prescient-re-builder))
	    ivy-prescient-sort-commands
	    '(:not ivy-switch-buffer
	           lsp-ivy-workspace-symbol ivy-resume ivy--restore-session
	           counsel-grep counsel-git-grep counsel-rg counsel-ag
	           counsel-ack counsel-fzf counsel-pt counsel-imenu
	           counsel-yank-pop counsel-recentf counsel-buffer-or-recentf))
  (ivy-prescient-mode 1))

;; Counsel takes Ivy further, providing versions of common Emacs commands that are customised to make the best use of Ivy.
(use-package counsel
  :defer t
  :diminish counsel-mode
  :custom
  (enable-recursive-minibuffers t) ;; Allow commands in minibuffers
  (counsel-find-file-ignore-regexp "^\\.\\|\\.elc\\'")
  :config
  (counsel-mode 1)
  ;; (defalias 'execute-extended-command 'counsel-M-x)
  :bind
  (("<f1> c" . 'describe-char)
   ("<f1> f" . 'counsel-describe-function)
   ("<f1> v" . 'counsel-describe-variable)
   ("<f1> l" . 'counsel-find-library)
   ("<f1> i" . 'counsel-info-lookup-symbol)
   ("<f1> u" . 'counsel-unicode-char)
   ("C-x C-f" . 'counsel-find-file)
   ("M-y" . 'counsel-yank-pop)
   :map counsel-mode-map
   ([remap dired] . counsel-dired)
   ([remap set-variable] . counsel-set-variable)
   ([remap insert-char] . counsel-unicode-char)
   ([remap recentf-open-files] . counsel-recentf)
   :map ivy-minibuffer-map
   ("M-y" . 'ivy-next-line)))

(provide '+ivy)

;;; +ivy.el ends here
